﻿//Author:Michal Sporna
//License: https://operationsneakpeek.codeplex.com/license

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;
using System.IO;
using Microsoft.Xna.Framework;

namespace Util.Helpers
{
    /// <summary>
    /// Read/Save XML
    /// used mostly to read configuration files
    /// </summary>
    public static class XMLParser
    {

        #region private fileds
        //private System.Xml.xml _XML;
        private static XDocument _XML;

        #endregion

        #region methods

        #region load and dispose
        /// <summary>
        /// Load XML from path
        /// </summary>
        /// <param name="path"></param>
        public static void LoadXML(string path)
        {
            try
            {
                ///Load XML for later processing
                _XML = XDocument.Load(path);

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// Load XML from x document
        /// </summary>
        /// <param name="path"></param>
        public static void LoadXML(XDocument xml)
        {
            try
            {
                ///Load XML for later processing
                _XML = xml;

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// Load XML from stream
        /// </summary>
        /// <param name="path"></param>
        public static void LoadXML(Stream xml)
        {
            try
            {
                
                ///Load XML for later processing
                _XML = XDocument.Load(xml);
                
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }

        /// <summary>
        /// Close&dispose from memory
        /// </summary>
        public static void FinishWorkingWithXML()
        {
            try
            {
                //dispose _XML from memory
                if (_XML != null)
                {
                    _XML = null;
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return;
            }
        }


        #endregion

        #region read Map XML

        /// <summary>
        /// Load Map
        /// </summary>
        /// <returns></returns>
        public static Levels.Map LoadMap()
        {
            //declare
            List<Levels.Map> list; //query will be converted to list (it will always have 1 element)

            try
            {

                //fill map with properties from the file
                list = (from query in _XML.Descendants("Map")
                        select new Levels.Map()
                        {
                            Name = (string)query.Element("name"),
                            Title = (string)query.Element("title"),
                            MapCells = (from mc in _XML.Descendants("MapCell")
                                        select new Levels.MapCell()
                                        {
                                            ID = (string)mc.Element("ID")

                                        }).ToList(),
                            WordPropositions = (from wp in _XML.Descendants("WordProposition")
                                                select new Classes.WordProposition()
                                                {
                                                    String=(string)wp.Element("String")

                                                }).ToList(),
                            LetterPlacements=(from lp in _XML.Descendants("LetterPlacement")
                                              select new Levels.LetterPlacement()
                                              {
                                                  MapCellID=(string)lp.Element("MapCellID"),
                                                  Word=(string)lp.Element("Word"),
                                                  Letter=(string)lp.Element("Letter"),
                                                  X=(int)lp.Element("X"),
                                                  Y=(int)lp.Element("Y"),
                                                  Index=(int)lp.Element("Index")

                                              }).ToList(),
                            PointsForFiding1Letter = (int)query.Element("PointsForFinding1Letter"),
                            PointsForFindingAllLetters = (int)query.Element("PointsForFindingAllLetters"),
                            PointsForGuessingPassword = (int)query.Element("PointsForGuessingPassword"),
                            PointsForDefusingBomb=(int)query.Element("PointsForDefusingBomb"),
                            PointsForDefusingBomb1=(int)query.Element("PointsForDefusingBomb1"),
                            PointsForDefusingBomb2=(int)query.Element("PointsForDefusingBomb2"),
                            PointsForDefusingBomb3=(int)query.Element("PointsForDefusingBomb3"),
                            DefaultWildPassGuessesNumber=(int)query.Element("DefaultWildPassGuessesNumber"),
                            NPCInfo=(from n in _XML.Descendants("NPC")
                                     select new Levels.NPCInfo()
                                     {
                                         Path=(string)n.Element("Path")
                                     }).ToList()
                        }).ToList();

             


                //return map if is not null
                if (list[0] != null)
                {
                    //set current map cell, first loaded map cell from MapCells
                    list[0].CurrentMapCell = list[0].MapCells[0];

                    

                    //set current map if this is a current map
                    if (list[0].IsCurrentMap)
                    {
                        Levels.LevelManager.CurrentMap = list[0];
                    }
                    

                    //and return a list of map cells
                    return list[0];
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;

            }
        }



        #endregion

        #region read MapCell XML

        /// <summary>
        /// Load Map Cell
        /// </summary>
        /// <returns></returns>
        public static Levels.MapCell LoadMapCell()
        {
            //declare
            List<Levels.MapCell> list; //query will be converted to list (it will always have 1 element)
            Measurement msrmnt; //measurement field used for validating obtained from the xml values

            try
            {

                //fill map with properties from the file
                list = (from query in _XML.Descendants("MapCell")
                        select new Levels.MapCell()
                        {
                            ID=(string)query.Attribute("name"),
                            Minutes=(double)query.Element("Time"),
                            Energy=(int)query.Element("Energy"),
                            HasAnyTrackableBombs=(bool)query.Element("HasAnyTrackableBombs"),
                            TexturesToDraw = (from t in _XML.Descendants("TextureToDraw")
                                              select new Util.Classes.TextureToDraw()
                                              {
                                                  Texture = (string)t.Element("texture"),
                                                  XString = (string)t.Element("locX"),
                                                  YString = (string)t.Element("locY"),
                                                  WidthString = (string)t.Element("width"),
                                                  HeightString = (string)t.Element("height")
                                              }).ToList(),
                            Obstacles=(from ob in _XML.Descendants("ObstacleToDraw")
                                       select new Util.Classes.ObstacleToDraw()
                                       {
                                           ObstacleID=(string)ob.Element("Name"),
                                           PosXString=(string)ob.Element("PosX"),
                                           PosYString=(string)ob.Element("PosY"),
                                           HasState2=(bool)ob.Element("HasState2"),
                                           ItemState2=(string)ob.Element("ItemState2"),
                                           Interactive = (bool)ob.Element("Interactive")
                                       }).ToList(),
                            
                            MovePatterns = (from mQuery in _XML.Descendants("MovePattern")
                                            select new Characters.Helpers.MovePattern()
                                            {
                                                NPCID=(string)mQuery.Element("NPC"),
                                                NPCCT=(int)mQuery.Element("NPCCT"),
                                                IsMoving=(bool)mQuery.Element("IsMoving"),
                                                StartXString = (string)mQuery.Element("StartX"),
                                                StartYString = (string)mQuery.Element("StartY"),
                                                EndXString = (string)mQuery.Element("EndX"),
                                                EndYString = (string)mQuery.Element("EndY"),
                                                MoveDirectionString = (string)mQuery.Element("Direction"),
                                                WaitTime = (double)mQuery.Element("WaitTime"),
                                                FieldsOfView = (from fQuery in mQuery.Descendants("FieldOfView")
                                                              select new Characters.Helpers.MasterFOV()
                                                              {
                                                                  Time=(int)fQuery.Element("Time"),
                                                                  OrderNumber=(int)fQuery.Element("OrderNumber"),
                                                                  Direction=(string)fQuery.Element("Direction"),
                                                                  Circles = (from cQuery in fQuery.Descendants("Circle")
                                                                                    select new Characters.Helpers.FOVCircle()
                                                                           {
                                                                                 Width=(int)cQuery.Element("Width"),
                                                                                 Height=(int)cQuery.Element("Height"),
                                                                                 CircleNumber=(int)cQuery.Element("CircleNumber"),
                                                                                 OrderNumber=(int)cQuery.Element("OrderNumber"),
                                                                                 OffsetX=(int)cQuery.Element("OffsetX"),
                                                                                 OffsetY=(int)cQuery.Element("OffsetY")
                                                                           }).ToList()
                                                               
                                                              }).ToList()

                                            }).ToList(),
                            Bombs=(from bQuery in _XML.Descendants("BombToDraw")
                                   select new Util.Classes.BombToDraw()
                                   {
                                       BombID=(string)bQuery.Element("ID"),
                                       Trackable=(bool)bQuery.Element("Trackable"),
                                       AvailablePositions=(from ap in bQuery.Descendants("BombPosition")
                                                           select new Util.Classes.BombPosition()
                                                           {
                                                               ID=(int)ap.Element("ID"),
                                                               X=(int)ap.Element("X"),
                                                               Y=(int)ap.Element("Y")
                                                           }).ToList(),
                                       IsHidden = (bool)bQuery.Element("IsHidden"),
                                       MustBeVisbleToDefuse = (bool)bQuery.Element("MustBeVisibleToDefuse")
                                   }).ToList(),
                            Requirements=(from rQuery in _XML.Descendants("Requirement")
                                          select new Levels.Requirement()
                                          {
                                              Description=(string)rQuery.Element("Description"),
                                              EntityID=(string)rQuery.Element("EntityID"),
                                              value=(int)rQuery.Element("Value"),
                                              EntityTypeString=(string)rQuery.Element("Entity"),
                                              RequiredActionString=(string)rQuery.Element("RequiredAction")

                                          }).ToList(),
                            CollectableItems=(from itQuery in _XML.Descendants("ItemToDraw")
                                              select new Util.Classes.ItemToDraw()
                                              {
                                                  ItemID=(string)itQuery.Element("ID"),
                                                  PosXString=(string)itQuery.Element("X"),
                                                  PosYString=(string)itQuery.Element("Y"),
                                                  Count=(int)itQuery.Element("Count")

                                              }).ToList(),
                            Portals=(from pQuery in _XML.Descendants("Portal")
                                     select new Levels.Portal()
                                     {
                                         ID=(string)pQuery.Element("ID"),
                                         XString=(string)pQuery.Element("X"),
                                         YString=(string)pQuery.Element("Y"),
                                         NextCell=(string)pQuery.Element("NextCell"),
                                         IsEnd=(bool)pQuery.Element("IsEnd"),
                                         AvatarPosInNextMapCell=new int[]{(int)pQuery.Element("AvatarPosX"),(int)pQuery.Element("AvatarPosY")}
                                     }).ToList(),
                            AvatarPlacement=(from qpQuery in _XML.Descendants("AvatarPlacement")
                                             select new Levels.AvatarPlacement()
                                             {
                                                 AvatarStartX=(int)qpQuery.Element("AvatarStartPosX"),
                                                 AvatarStartY=(int)qpQuery.Element("AvatarStartPosY"),
                                                 AvatarStateString=(string)qpQuery.Element("AvatarState")
                                             }).ToList()
                        }).ToList();




                //return map if is not null
                if (list[0] != null)
                {
                    //validate measurements
                    //textures to draw
                    foreach (Util.Classes.TextureToDraw ttd in list[0].TexturesToDraw)
                    {
                        msrmnt = new Measurement();
                        msrmnt.Y = 0;
                        msrmnt.X = 0;
                        msrmnt = Utilities.ValidateAndConvertMeasurements(ttd.XString, ttd.YString, ttd.WidthString, ttd.HeightString);
                        //assign values to ttd
                        ttd.X = msrmnt.X;
                        ttd.Y = msrmnt.Y;
                        ttd.Width = msrmnt.Width;
                        ttd.Height = msrmnt.Height;
                        //dispose of msrmt
                        msrmnt = null;
                        //clear ttd strings (will not be used anymore)
                        ttd.HeightString = null;
                        ttd.WidthString = null;
                        ttd.XString = null;
                        ttd.YString = null;
                    }
                    //Portals
                    if (list[0].Portals != null && list[0].Portals.Count>0)
                    {
                        foreach (Levels.Portal p in list[0].Portals)
                        {
                            msrmnt = new Measurement();
                            msrmnt.Y = 0;
                            msrmnt.X = 0;
                            msrmnt = Utilities.ValidateAndConvertMeasurements(p.XString, p.YString, string.Empty, string.Empty);
                            p.X = msrmnt.X;
                            p.Y = msrmnt.Y;
                            p.XString = null;
                            p.YString = null;
                            msrmnt = null;
                        }
                    }
                    //Process obstacles
                    foreach (Util.Classes.ObstacleToDraw otd in list[0].Obstacles)
                    {
                        msrmnt = Utilities.ValidateAndConvertMeasurements(otd.PosXString, otd.PosYString, null, null);
                        otd.Position = new Vector2(msrmnt.X, msrmnt.Y);
                        //clear
                        otd.PosXString = null;
                        otd.PosYString = null;
                        msrmnt = null;

                    }
                    //process items
                    foreach (Util.Classes.ItemToDraw itd in list[0].CollectableItems)
                    {
                        msrmnt = Utilities.ValidateAndConvertMeasurements(itd.PosXString, itd.PosYString, null, null);
                        itd.Position = new Vector2(msrmnt.X, msrmnt.Y);
                        //clear
                        itd.PosXString = null;
                        itd.PosYString = null;
                        msrmnt = null;


                    }
                    //process bombs
                    //NEW:
                    if (list[0].Bombs != null)
                    {
                        //choose 1 position randomly from all postitions assigned to the bomb
                        foreach (Util.Classes.BombToDraw btd in list[0].Bombs)
                        {
                            btd.SetPosition();
                        }

                    }

                    //process avatar placement in map cell
                    if (list[0].AvatarPlacement != null)
                    {
                        foreach (Levels.AvatarPlacement ap in list[0].AvatarPlacement)
                        {
                            ap.ConvertAvatarState();
                        }
                    }

                    //foreach (Util.Classes.BombToDraw btd in list[0].Bombs)
                    //{
                    //    msrmnt = Utilities.ValidateAndConvertMeasurements(btd.PosXString, btd.PosYString, null, null);
                    //    btd.Position = new Vector2(msrmnt.X, msrmnt.Y);
                    //    //clear
                    //    btd.PosXString = null;
                    //    btd.PosYString = null;
                    //    msrmnt = null;


                    //}
                    //process requirements
                    foreach (Levels.Requirement req in list[0].Requirements)
                    {
                        req.ConvertHelpersToValues();
                    }

                    //convert positions of move patterns
                    foreach (Characters.Helpers.MovePattern mp in list[0].MovePatterns)
                    {
                        mp.ConvertMeasurements();
                     
                    
                    }
                    //process letter prohibited spots

                    #region OBSOLETE AS OF 30.03
                    //if (list[0].ProhibitedNodesForLetters == null)
                    //{
                    //    list[0].ProhibitedNodesForLetters = new List<int[]>();
                    //}

                    //foreach (Classes.LetterProhibitedSpot lps in list[0].LetterProhibitedSpotsTempList)
                    //{
                    //    lps.ConvertToAList(list[0]);
                    //}
                    //delete the demp list of prohibited letter spots
                    //list[0].LetterProhibitedSpotsTempList = null;
                    #endregion

                    return list[0];
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;

            }
        }




        #endregion

        #region read obstacles XML

        /// <summary>
        /// Load Obstacle
        /// </summary>
        /// <returns></returns>
        public static Util.Classes.Obstacle LoadObstacle()
        {
            //declare
            List<Util.Classes.Obstacle> list; //query will be converted to list (it will always have 1 element)
            

            try
            {
                //fill map with properties from the file
                list = (from query in _XML.Descendants("Obstacle")
                        select new Util.Classes.Obstacle()
                        {
                            ID = (string)query.Attribute("name"),
                            Width=(int)query.Element("Width"),
                            Height=(int)query.Element("Height"),
                            ObstacleTypeString=(string)query.Element("Type"),
                            DynamicChangeTime=(double)query.Element("DynamicChangeTime"),
                            HarmMultiplier=(int)query.Element("HarmMultiplier"),
                            TextureName=(string)query.Element("TextureName"),
                            OffsetUp=(int)query.Element("OffsetUp"),
                            OffsetDown = (int)query.Element("OffsetDown"),
                            OffsetRight = (int)query.Element("OffsetRight"),
                            OffsetLeft = (int)query.Element("OffsetLeft"),
                            ItemsInteracting=(from q in _XML.Descendants("InteractingItems")
                                              select new Helpers.ObstacleInteractingItemHelper()
                                              {
                                                  InteractingItem=(string)q.Element("InteractingItem")

                                              }).ToList(),
                            IsWater=(bool)query.Element("IsWater"),
                            Walkable=(bool)query.Element("Walkable"),
                            ShieldTypeString=(string)query.Element("ShieldType"),
                            Events = (from eQuery in _XML.Descendants("Event")
                                      select new Util.Classes.Event()
                                      {
                                          Method = (string)eQuery.Element("Method"),
                                          EventTypeString = (string)eQuery.Element("Type"),
                                          Parameters = (from pQuery in _XML.Descendants("Parameter")
                                                        select new Util.Classes.EventParameter()
                                                        {
                                                            ParameterString = (string)pQuery.Element("Value")

                                                        }).ToList()

                                      }).ToList()
                        }).ToList();




                //if obstacle is not null, process and return
                if (list[0] != null)
                {
                    //process obstacleType
                    #region convert string obstacle type to enum obstacle type
                    switch (list[0].ObstacleTypeString)
                    {
                        case "StaticNoHarm":
                            {
                                list[0].Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarm;

                                break;
                            }
                        case "StaticNoHarmInteractive":
                            {
                                list[0].Type = Util.Helpers.PublicEnums.ObstacleType.StaticNoHarmInteractive;

                                break;
                            }
                        case "StaticHarm":
                            {
                                list[0].Type = Util.Helpers.PublicEnums.ObstacleType.StaticHarm;

                                break;
                            }
                        case "MovingHarm":
                            {
                                list[0].Type = Util.Helpers.PublicEnums.ObstacleType.MovingHarm;

                                break;
                            }


                    }

                    //celar obstacleTypeString
                    list[0].ObstacleTypeString = null;


                    #endregion

                    list[0].DoConvertions();

                    return list[0];
                }
                else
                {
                    return null;
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;

            }

        }

        #endregion

        #region read items XML

        /// <summary>
        /// return item loaded from xml
        /// </summary>
        /// <returns></returns>
        public static Util.Classes.Item LoadItem()
        {
            //declare
            List<Util.Classes.Item> Items;
          


            try
            {


                Items = (from query in _XML.Descendants("Item")
                         select new Util.Classes.Item()
                         {
                             Name=(string)query.Attribute("name"),
                             Width=(double)query.Element("Width"),
                             Height=(double)query.Element("Height"),
                             Offset=(double)query.Element("Offset"),
                             Efficiency=(double)query.Element("Efficiency"),
                             VisibleInInventory=(bool)query.Element("VisibleInInventory"),
                             ActionTypeString=(string)query.Element("Action"),
                             HasState2=(bool)query.Element("HasState2"),
                             ItemState2=(string)query.Element("ItemState2"),
                             TextureName=(string)query.Element("TextureName"),
                             Event = (from eQuery in _XML.Descendants("Event")
                                       select new Util.Classes.Event()
                                       {
                                           Method = (string)eQuery.Element("Method"),
                                           EventTypeString = (string)eQuery.Element("Type"),
                                           Parameters = (from pQuery in _XML.Descendants("Parameter")
                                                         select new Util.Classes.EventParameter()
                                                         {
                                                             ParameterString = (string)pQuery.Element("Value")

                                                         }).ToList()

                                       }).ToList()
                         }).ToList();

                //continue if item loaded (list not null)
                if (Items[0] != null)
                {
                    //do convertions
                    Items[0].DoConvertions();
                    //return
                    return Items[0];
                }
                else
                {
                    return null;
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }
        }



        #endregion


        #region read Bomb XML

        /// <summary>
        /// return bomb loaded from xml
        /// </summary>
        /// <returns></returns>
        public static Util.Classes.Bomb LoadBomb()
        {
            //declare
            List<Util.Classes.Bomb> bombs;



            try
            {


                bombs = (from query in _XML.Descendants("Bomb")
                         select new Util.Classes.Bomb()
                         {
                             Name=(string)query.Attribute("name"),
                             Texture=(string)query.Element("TextureName"),
                             TextureInactive=(string)query.Element("InactiveTextureName"),
                             Width=(double)query.Element("Width"),
                             Height=(double)query.Element("Height"),
                             ExplosionTypeString=(string)query.Element("Explosion"),
                             BonusTime=(int)query.Element("BonusTime"),
                             Difficulty=(int)query.Element("Difficulty"),
                             DefusingWireGracePeriod=(double)query.Element("DefusingWireGracePeriod"),
                             TimeToSubtractOnBombFailed=(double)query.Element("TimeToTakeAwayOnFail"),
                             Events = (from eQuery in _XML.Descendants("Event")
                                      select new Util.Classes.Event()
                                      {
                                          Method = (string)eQuery.Element("Method"),
                                          EventTypeString = (string)eQuery.Element("Type"),
                                          Parameters = (from pQuery in _XML.Descendants("Parameter")
                                                        select new Util.Classes.EventParameter()
                                                        {
                                                            ParameterString = (string)pQuery.Element("Value")

                                                        }).ToList()

                                      }).ToList(),
                            ShuffleHelperList=(from sQuery in _XML.Descendants("Shuffle")
                                     select new Util.Classes.BombWireShuffle()
                                     {
                                         ShufflePeriod=(int)sQuery.Element("ShufflePeriod"),
                                         ShuffleSpeed=(double)sQuery.Element("ShuffleSpeed"),
                                         Turns=(from tQuery in sQuery.Descendants("ShuffleTurn")
                                                select new Util.Classes.BombWireShuffleTurn()
                                                {
                                                    Moves=(from mQuery in tQuery.Descendants("Move")
                                                            select new Util.Classes.BombWireShuffleMove()
                                                            {
                                                                MoveTypeString=(string)mQuery.Element("Text")
                                                            
                                                            }).ToList()

                                                }).ToList()
                                     }).ToList(),
                            Wires=(from wQuery in _XML.Descendants("Wire")
                                   select new Util.Classes.BombWire()
                                   {
                                       Color=(string)wQuery.Element("Color"),
                                       Texture=(string)wQuery.Element("Texture"),
                                       Width=(double)wQuery.Element("Width"),
                                       Height=(double)wQuery.Element("Height"),
                                       DissolveSpeed=(int)wQuery.Element("DissolveSpeed")
                                   }).ToList()

  

                         }).ToList();

                //continue if item loaded (list not null)
                if (bombs[0] != null)
                {
                    #region parse explosion type
                    //parse
                    bombs[0].DoConversions();


                    #endregion



                    return bombs[0];
                }
                else
                {
                    return null;
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;
            }
        }








        #endregion


        #region read NPCs XML

        /// <summary>
        /// Load Obstacle
        /// </summary>
        /// <returns></returns>
        public static Characters.NPC LoadNPC()
        {
            ////declare
            List<Characters.NPC> list; //query will be converted to list (it will always have 1 element)
    

            try
            {
                //fill map with properties from the file
                list = (from query in _XML.Descendants("NPC")
                        select new Characters.NPC()
                        {
                            ID = (string)query.Element("Name"),
                            NPCTypeString=(string)query.Element("NPCType"),
                            Textures=(from tQuery in _XML.Descendants("Texture")
                                      select new Characters.Helpers.NPCTexture()
                                      {
                                         ID=(string)tQuery.Element("ID"),
                                         Direction=(string)tQuery.Element("Direction"),
                                         TextureTypeString=(string)tQuery.Element("type")

                                      }).ToList(),
                                         
                            Width=(int)query.Element("Width"),
                            Height=(int)query.Element("Height"),
                            Step=(int)query.Element("Step"),
                            //PartIDs=(from pQuery in _XML.Descendants("Part")
                            //         select new Levels.MapCellInfo()
                            //         {
                            //             MapCellID=(string)pQuery.Element("ID")
                            //         }).ToList(),
                            Map=(string)query.Element("Map"),
                            WeaponID=(string)query.Element("WeaponID"),
                            Strength=(int)query.Element("Strength"),
                            Perception=(int)query.Element("Perception"),
                            Luck=(int)query.Element("Luck"),
                            IQ=(int)query.Element("IQ"),
                            SpecialAbilityID=(string)query.Element("SpecialAbility"),
                            Health=(int)query.Element("Health"),
                            Events=(from eQuery in _XML.Descendants("Event")
                                    select new Util.Classes.Event()
                                    {
                                        Method=(string)eQuery.Element("Method"),
                                        EventTypeString=(string)eQuery.Element("Type"),
                                        Parameters=(from pQuery in _XML.Descendants("Parameter")
                                                    select new Util.Classes.EventParameter()
                                                    {
                                                        ParameterString=(string)pQuery.Element("Value")

                                                    }).ToList()

                                    }).ToList()
                        }).ToList();




                //if obstacle is not null, process and return
                if (list[0] != null)
                {
                    //process obstacleType
                    #region convert string values to numeric values,strings to enums etc.

                    list[0].DoConversions();//also adds unique ID


                    #endregion



                    return list[0];
                }
                else
                {
                    return null;
                }

        

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;

            }

        }

        #endregion

        #region read world config xml

        /// <summary>
        /// Load World Config
        /// </summary>
        /// <returns></returns>
        public static World.WorldConfig LoadWorldConfig()
        {
            //declare
            List<World.WorldConfig> list; //query will be converted to list (it will always have 1 element)
            

            try
            {
                //fill map with properties from the file
                list = (from query in _XML.Descendants("WorldConfig")
                        select new World.WorldConfig()
                        {
                            GameTitle = (string)query.Element("GameTitle"),
                            Maps=(from mQuery in _XML.Descendants("Map")
                                  select new Levels.MapInfo()
                                  {
                                      Title=(string)mQuery.Element("Name"),
                                      ID=(string)mQuery.Element("ID"),
                                      Path=(string)mQuery.Element("Path"),
                                      Order=(int)mQuery.Element("Order"),
                                      StarsNeededToUnlock=(int)mQuery.Element("StarsNeededToUnlock"),
                                      PreviousMapID=(string)mQuery.Element("PreviousMapID")
                                      
                                  }).ToList(),
                            NpcPlacement=(from nQuery in _XML.Descendants("NPCPlacement")
                                          select new Levels.npcPlacement()
                                          {
                                              ID=(string)nQuery.Element("ID"),
                                              Number=(int)nQuery.Element("Number"),
                                              MapID=(string)nQuery.Element("MapID"),
                                              MapCell=(string)nQuery.Element("MapCell")
                                          }).ToList(),
                            ObstaclePlacement=(from oQuery in _XML.Descendants("ObstaclePlacement")
                                               select new Levels.ObstaclePlacement()
                                               {
                                                   ObstacleID=(string)oQuery.Element("ObstacleID"),
                                                   MapID=(string)oQuery.Element("MapID"),
                                                   MapCellID=(string)oQuery.Element("MapCellID")
                                               }).ToList(),
                            ItemPlacement=(from iQuery in _XML.Descendants("ItemPlacement")
                                           select new Levels.ItemPlacement()
                                           {
                                               ItemID=(string)iQuery.Element("ItemID"),
                                               MapID=(string)iQuery.Element("MapID"),
                                               MapCellID=(string)iQuery.Element("MapCellID")
                                           }).ToList(),
                            TexturePlacement=(from tQuery in _XML.Descendants("TexturePlacement")
                                              select new Levels.TexturePlacement()
                                              {
                                                  TextureID = (string)tQuery.Element("TextureID"),
                                                  MapID = (string)tQuery.Element("MapID"),
                                                  MapCellID = (string)tQuery.Element("MapCellID")


                                              }).ToList(),
                            BombPlacement=(from bQuery in _XML.Descendants("BombPlacement")
                                           select new Levels.BombPlacement()
                                           {
                                                  BombID = (string)bQuery.Element("BombID"),
                                                  MapID = (string)bQuery.Element("MapID"),
                                                  MapCellID = (string)bQuery.Element("MapCellID")
                                           }).ToList(),
                            BreathTakeawayTime = (int)query.Element("BreathTakeAwayTime"),
                            BreathTakeawayValue = (int)query.Element("BreathTakeAwayValue"),
                            InventorySlotHeight = (int)query.Element("InventorySlotHeight"),
                            InventorySlotWidth = (int)query.Element("InventorySlotWidth"),
                            InventorySlotCountFrameHeight = (int)query.Element("InventorySlotCountFrameHeight"),
                            InventorySlotNameFrameHeight = (int)query.Element("InventorySlotNameFrameHeight"),
                            BombScannerTimeElapsing = (double)query.Element("BombScannerTimeElapsing"),
                            TimeToUncoverNextNode = (double)query.Element("TimeToUncoverNextNode"),
                            TimeOffsetToPhase2 = (double)query.Element("TimeOffsetToPhase2"),
                            BombUncoverAnimationTime = (double)query.Element("BombUncoverAnimationTime"),
                            UncoverEnergyCost = (int)query.Element("UncoverEnergyCost"),
                            EnergyBarHeight = (int)query.Element("EnergyBarHeight"),
                            RedPointerFlashTimeON = (double)query.Element("RedPointerFlashTimeON"),
                            RedPointerFlashTimeOFF = (double)query.Element("RedPointerFlasTimeOFF"),
                            AvatarHeight = (int)query.Element("AvatarHeight"),
                            AvatarWidth = (int)query.Element("AvatarWidth"),
                            AvatarWalkSpeed = (int)query.Element("AvatarWalkSpeed"),
                            MapSelectorFrameWidth = (int)query.Element("MapSelectorFrameWidth"),
                            MapSelectorFrameHeight = (int)query.Element("MapSelectorFrameHeight"),
                            MapSelectorTitleFrameHeight = (int)query.Element("MapSelectorTitleFrameHeight"),
                            MapSelectorStatisticsFrameHeight = (int)query.Element("MapSelectorStatisticsFrameHeight"),
                            CheckpointHeight = (int)query.Element("CheckpointHeight"),
                            CheckpointWidth = (int)query.Element("CheckpointWidth"),
                            NodeWidth = (int)query.Element("NodeWidth"),
                            NodeHeight = (int)query.Element("NodeHeight"),
                            MarkerWidth = (int)query.Element("MarkerWidth"),
                            MarkerHeight = (int)query.Element("MarkerHeight"),
                            scannerMapContextMenuButtonWidth = (int)query.Element("ScannerMapContextMenuButtonWidth"),
                            ScannerMapContextMenuButtonHeight = (int)query.Element("ScannerMapContextMenuButtonHeight"),
                            ScannerMapContextMenuWidth = (int)query.Element("ScannerMapContextMenuWidth"),
                            ScannerMapContextMenuHeight = (int)query.Element("ScannerMapContextMenuHeight"),
                            DefaultRedMarkerCount = (int)query.Element("DefaultRedMarkerCount"),
                            DefautlGreenMarkerCount = (int)query.Element("DefaultGreenMarkerCount"),
                            DefautlOrangeMarkerCount = (int)query.Element("DefaultOrangeMarkerCount"),
                            NodeVeryColdValue = (float)query.Element("NodeVeryColdValue"),
                            NodeColdValue = (float)query.Element("NodeColdValue"),
                            NodeWarmValue = (float)query.Element("NodeWarmValue"),
                            NodeHotValue = (float)query.Element("NodeHotValue"),
                            NodeVeryHotValue = (float)query.Element("NodeVeryHotValue"),
                            ScannerDifficulty = (int)query.Element("ScannerDifficulty"),
                            AutoScannerDifficulty = (int)query.Element("AutoScannerDifficulty"),
                            AutoScannerBatteryRefillTime = (int)query.Element("AutoScannerBatteryRefillTime"),
                            RefillValue = (int)query.Element("RefillValue"),
                            BatteryUsageStep = (int)query.Element("BatteryUsageStep"),
                            TakeAwayValue = (int)query.Element("TakeAwayValue"),
                            BatteryBarWidth = (int)query.Element("BatteryBarWidth"),
                            BombDefusingCancelButtonWidth = (int)query.Element("BombDefusingCancelButtonWidth"),
                            BombDefusingCancelButtonHeight = (int)query.Element("BombDefusingCancelButtonHeight"),
                            AvatarHealth = (int)query.Element("AvatarHealth"),
                            DefaultEnergyValue = (int)query.Element("DefaultEnergyValue"),
                            PointsNeededFor1Star = (int)query.Element("PointsNeededFor1Star"),
                            PointsNeededFor2Stars = (int)query.Element("PointsNeededFor2Stars"),
                            PointsNeededFor3Stars = (int)query.Element("PointsNeededFor3Stars"),
                            LetterFontFace = (string)query.Element("LetterFontFace"),
                            LetterUncoverAnimationTime = (double)query.Element("LetterUncoverAnimationTime")
                        }).ToList();


                //if config is not null, process and return
                if (list[0] != null)
                {
                    //load star number from storage for each map 
                    for (int i = 0; i < list[0].Maps.Count; i++)
                    {
                        //points
                        list[0].Maps[i].Points = World.StorageManager.LoadPointsForTheMap(list[0].Maps[i].ID);
                        //stars
                        list[0].Maps[i].Stars=World.StorageManager.LoadStarsForTheMap(list[0].Maps[i].ID);
                    }

                    list[0].InitProperties();


                    return list[0];
                }
                else
                {
                    return null;
                }

            }
            catch (Exception ex)
            {
                Util.ErrorLogging.LogError(ex);
                return null;

            }

        }



        #endregion

        #endregion

    }
}
